package org.jiaxin.nutrient.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.javatuples.Pair;
import org.javatuples.Triplet;

import org.jiaxin.nutrient.bean.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jiaxin
 * @version 1.0
 * @description: TODO
 * @date 2024/5/21 23:54
 */
public class DietaryUtils {
    private static Logger logger= LoggerFactory.getLogger(DietaryUtils.class);


    public static void main(String[] args) throws Exception {
        //这里要读取用户的食谱信息，如果用户是新注册的用户没有食谱的话，返回空值
        DBTemplate<UserInfo> instance = DBTemplate.getInstance();
        String sql = "select * from user_info where user_name='" + "张三" + "'";
        System.out.println("getUser " + sql);

        List<UserInfo> sqlData = instance.getSqlData(sql, UserInfo.class);
        System.out.println("userSize: " + sqlData.size());
        instance.close();
       /* for (UserInfo sqlDatum : sqlData) {
            //如果为空的话 返回
            if (StringUtils.isBlank(sqlDatum.getDietaryPrefer())) {
                //return CommonUtils.returnMap("饮食图谱为空，请您填写必要的问卷！", 300);
            } else {
                DBTemplate<DietaryRecommendDaily> dietaryRecommendDailyDBTemplate = DBTemplate.getInstance();
                //查询 推荐图谱的记录表
                String re_sql = "select * from dietary_recommend_daily where user_name = '${user_name}' and date(update_time)= '${update_time}'";
                re_sql = re_sql.replace("${user_name}", "张三")
                        .replace("${update_time}", DateTimeUtils.getNowDate());

                List<DietaryRecommendDaily> dailyDBTemplateSqlData = dietaryRecommendDailyDBTemplate.getSqlData(re_sql, DietaryRecommendDaily.class);

                Map<String, DietaryRecommendDaily> dietaryRecommendDailyMap;


                if (dailyDBTemplateSqlData.isEmpty()) {
                    //如果当日的 饮食图谱没有生成， 那么返回饮食图谱
                    dietaryRecommendDailyMap = DietaryUtils.getDietaryGraph(sqlDatum);
                    //写入到数据库
                    DietaryUtils.saveDietaryGraph(dietaryRecommendDailyDBTemplate, dietaryRecommendDailyMap, "张三");
                } else {
                    //如果当日的饮食图谱已经生成了  那么 直接返回即可
                    *//*Map<String,> dietaryGraph = new HashMap<>();*//*
                    dietaryRecommendDailyMap = new HashMap<>();
                    for (DietaryRecommendDaily datum : dailyDBTemplateSqlData) {
                        if ("谷物及制品".equals(datum.getCate1())) {
                            dietaryRecommendDailyMap.put("谷物及制品", datum);
                        } else if ("薯类、淀粉及制品".equals(datum.getCate1())) {
                            dietaryRecommendDailyMap.put("薯类、淀粉及制品", datum);
                        } else if ("干豆类及制品".equals(datum.getCate1())) {
                            dietaryRecommendDailyMap.put("干豆类及制品", datum);
                        } else if ("蔬菜及制品".equals(datum.getCate1())) {
                            dietaryRecommendDailyMap.put("蔬菜及制品", datum);
                        } else if ("畜肉类及制品".equals(datum.getCate1())) {
                            dietaryRecommendDailyMap.put("畜肉类及制品", datum);
                        } else if ("禽肉类及制品".equals(datum.getCate1())) {
                            dietaryRecommendDailyMap.put("禽肉类及制品", datum);
                        } else if ("蛋类及制品".equals(datum.getCate1())) {
                            dietaryRecommendDailyMap.put("蛋类及制品", datum);
                        } else if ("鱼虾蟹贝类".equals(datum.getCate1())) {
                            dietaryRecommendDailyMap.put("鱼虾蟹贝类", datum);
                        }
                    }

                }

                System.out.println("dietaryRecommendDailyMap: "+dietaryRecommendDailyMap);
                //对食谱进行 格式化 nodes  edges
                JSONArray nodes = DietaryUtils.formatNodes(dietaryRecommendDailyMap, "张三");
                JSONArray edges = DietaryUtils.formatEdge(dietaryRecommendDailyMap);
                System.out.println("nodes: " + nodes);
                System.out.println("edges: " + edges);
            }
        }*/
    }



    public static Map<String,DietaryRecommendDaily> getDietaryGraph(UserInfo sqlDatum) throws Exception {


        String dietaryPrefer = sqlDatum.getDietaryPrefer();
        String gender = sqlDatum.getGender();
        //System.out.println("dietaryPrefer: "+dietaryPrefer);


        //
        DBTemplate<DietaryPrefer> dietaryPreferDBTemplate = DBTemplate.getInstance();

        String selectSql="select * from dietary_prefer where ";
       // 先区分性别
        if ("男性".equals(gender)){
            selectSql=selectSql+" gender = '男性'";
        }else if ("女性".equals(gender)){
            selectSql=selectSql+" gender = '女性'";
        }

        String finalSql = dietaryPreferSelector(selectSql, dietaryPrefer);
        System.out.println(finalSql);
        DietaryPrefer dietaryPreferAll = dietaryPreferDBTemplate.getSqlOneData(finalSql, DietaryPrefer.class);

        Map<String, DietaryRecommendDaily> stringTJMap = genDietaryPreferPlan(dietaryPreferAll);

        dietaryPreferDBTemplate.close();

        return stringTJMap;
    }

    private static String dietaryPreferSelector(String selectSql,String dietaryPrefer){


        //区分不同的饮食习惯
        switch (dietaryPrefer) {
            case "高蛋白饮食":
                selectSql=selectSql+" and dietary_prefer='高蛋白饮食' ";
                break;
            case "低蛋白饮食":
                selectSql=selectSql+" and dietary_prefer='低蛋白饮食' ";
                break;
            case "低碳水饮食":
                selectSql=selectSql+" and dietary_prefer='低碳水饮食' ";
                break;
            case "生酮饮食":
                selectSql=selectSql+" and dietary_prefer='生酮饮食' ";
                break;
            case "低脂肪饮食":
                selectSql=selectSql+" and dietary_prefer='低脂肪饮食' ";
                break;
            case "低卡饮食":
                selectSql=selectSql+" and dietary_prefer='低卡饮食' ";
                break;
            case "健康饮食":
                selectSql=selectSql+" and dietary_prefer='健康饮食' ";
                break;
        }

        return selectSql;

    }


    private static Map<String, DietaryRecommendDaily> genDietaryPreferPlan(DietaryPrefer dietaryPreferAll) throws Exception {
        //                     water_rate_range     calorie_range   protein_range   fat_range   carbohydrate_range  vitamin_a_range
        //1	男性	高蛋白饮食	700-1000	        1800-2250	    100-200	        50-80	    150-300	            700-800	            2024-05-21 22:38:52	2024-05-21 22:38:52

        //1. 获取所有食物的营养成分表
        DBTemplate<NutrientsInfo> instance = DBTemplate.getInstance();
        Random random = new Random();
        List<NutrientsInfo> nutrientsInfo = instance.getTableAllData("nutrients_info", NutrientsInfo.class);

        //2. 我们的推荐原则是 每一个大类 cate1 里都要涉及至少一个 cate2。并将所有食物的元素 符合我们指定的目标

        //2.1 先算水
        Pair<Integer, Integer> waterPair = startAndEnd(dietaryPreferAll.getWaterRateRange());
        // 根据水的范围 随机取出一个随机数
        int waterValue=waterPair.getValue0()+random.nextInt(waterPair.getValue1()-waterPair.getValue0());


        //2.2 根据 卡路里的范围 随机取出一个随机数
        Pair<Integer, Integer> CaloriePair = startAndEnd(dietaryPreferAll.getCalorieRange());
        int calorieValue=CaloriePair.getValue0()+random.nextInt(CaloriePair.getValue1()-CaloriePair.getValue0());


        //2.3 根据 蛋白质的范围 随机取出一个随机数
        Pair<Integer, Integer> proteinPair = startAndEnd(dietaryPreferAll.getProteinRange());
        int proteinValue=proteinPair.getValue0()+random.nextInt(proteinPair.getValue1()-proteinPair.getValue0());



        //2.4 根据 脂肪的范围 随机取出一个随机数
        Pair<Integer, Integer> fatPair = startAndEnd(dietaryPreferAll.getFatRange());
        int fatValue=fatPair.getValue0()+random.nextInt(fatPair.getValue1()-fatPair.getValue0());


        //2.5 根据 碳水化合物 的范围 随机取出一个随机数
        Pair<Integer, Integer> CarbohydratePair = startAndEnd(dietaryPreferAll.getCarbohydrateRange());
        int carbohydrateValue=CarbohydratePair.getValue0()+random.nextInt(CarbohydratePair.getValue1()-CarbohydratePair.getValue0());

        //2.6 根据 维生素A 的范围 随机取出一个随机数
        Pair<Integer, Integer> VitaminAPair = startAndEnd(dietaryPreferAll.getVitaminARange());
        int vitaminAValue=VitaminAPair.getValue0()+random.nextInt(VitaminAPair.getValue1()-VitaminAPair.getValue0());




        //3. 取出 每一个元素的平均值  然后在 元素中选择 那个离得最近选择哪个

        double avgWaterValue=waterValue*1.0/8;
        double avgCalorieValue=calorieValue*1.0/8;
        double avgProteinValue=proteinValue*1.0/8;
        double avgFatValue=fatValue*1.0/8;
        double avgCarbohydrateValue=carbohydrateValue*1.0/8;
        double avgVitaminAValue=vitaminAValue*1.0/8;


        //List<Double> avgList = Arrays.asList(avgWaterValue, avgCalorieValue, avgProteinValue, avgFatValue, avgCarbohydrateValue, avgVitaminAValue);

        LinkedHashMap<String, Double> avgMap = new LinkedHashMap<>();

        avgMap.put("water",avgWaterValue);  // 每一个元素的目标平均值
        System.out.println("water:"+avgWaterValue);

        avgMap.put("calorie",avgCalorieValue);
        System.out.println("calorie:"+avgCalorieValue);


        avgMap.put("protein",avgProteinValue);
        System.out.println("protein:"+avgProteinValue);


        avgMap.put("fat",avgFatValue);
        System.out.println("fat:"+avgFatValue);


        avgMap.put("carbohydrate",avgCarbohydrateValue);
        System.out.println("carbohydrate:"+avgCarbohydrateValue);

        avgMap.put("vitamina",avgVitaminAValue);
        System.out.println("vitamina:"+avgVitaminAValue);


        //求出了每个 cate1 中最优解
        Map<String, Optional<DietaryRecommendDaily>> bestValue = getCate2(avgMap, nutrientsInfo);


        //将 Optional变成TJ
        Map<String, DietaryRecommendDaily> dietaryRecommendDailyHashMap = new HashMap<>();


        Set<String> keySet = bestValue.keySet();
        for (String key : keySet) {
            dietaryRecommendDailyHashMap.put(key,bestValue.get(key).get());
        }


        return dietaryRecommendDailyHashMap;

    }


    private static Pair<Integer,Integer> startAndEnd(String pair) {

        String[] split = pair.split("-");
        return new Pair<>(Integer.parseInt(split[0]) ,Integer.parseInt(split[1]));
    }


    private static Map<String,Optional<DietaryRecommendDaily>> getCate2(Map<String,Double> avgValue, List<NutrientsInfo> nutrientsInfo){
        //这个 系数 我们可以随机选择，原则上这个最大值是 某个cate1 种类中含有元素的 最小值*系数<= avgValue
        List<String> cate1List = Arrays
                .asList("谷物及制品", "薯类、淀粉及制品", "干豆类及制品", "蔬菜及制品", "畜肉类及制品", "禽肉类及制品", "蛋类及制品", "鱼虾蟹贝类");
        Set<String> keySet = avgValue.keySet();
        double finalAvg=0;
        LinkedList<Triplet<String, String, Double>> triplets = new LinkedList<>();
        for (String cate1 : cate1List) {
            for (String nutrientsType : keySet) {
                //每一个元素
                Triplet<String, String, Double> triplet = calculateModulus(nutrientsType, nutrientsInfo, avgValue.get(nutrientsType), cate1);
                finalAvg=finalAvg+avgValue.get(nutrientsType); // 任意一个 cate1 的 所有元素的目标和 (额定总量)
                //System.out.println(finalAvg);
                //System.out.println(triplet);
                triplets.add(triplet);
            }

        }

        //
        ArrayList<DietaryRecommendDaily> dietaryRecommendDailyList = new ArrayList<>();



        for (NutrientsInfo info : nutrientsInfo) {
            double water=0;
            double calorie=0;
            double protein=0;
            double fat=0;
            double carbohydrate=0;
            double vitamina=0;
            DietaryRecommendDaily dietaryRecommendDaily = null;

            if ("谷物及制品".equals(info.getCate1())){
                // cate1 的 每一个元素 的 系数 (也就是 量)
                List<Triplet<String, String, Double>> collect = triplets.stream().filter(item -> "谷物及制品".equals(item.getValue0())).toList();
                dietaryRecommendDaily=panduan(info, water, calorie, protein, fat, carbohydrate, vitamina, collect);
                dietaryRecommendDaily.setCate1("谷物及制品");

         }else if ("薯类、淀粉及制品".equals(info.getCate1())){
                List<Triplet<String, String, Double>> collect = triplets.stream().filter(item -> "薯类、淀粉及制品".equals(item.getValue0())).toList();
                 dietaryRecommendDaily =panduan(info, water, calorie, protein, fat, carbohydrate, vitamina, collect);
                dietaryRecommendDaily.setCate1("薯类、淀粉及制品");
                //System.out.println("薯类、淀粉及制品 最后的结果值："+total+" 最优值是："+finalAvg/8+" 相差 "+Math.abs(total-finalAvg/8));
            }else if ("干豆类及制品".equals(info.getCate1())){
                List<Triplet<String, String, Double>> collect = triplets.stream().filter(item -> "干豆类及制品".equals(item.getValue0())).toList();
                 dietaryRecommendDaily =panduan(info, water, calorie, protein, fat, carbohydrate, vitamina, collect);
                //System.out.println("干豆类及制品 最后的结果值："+total+" 最优值是："+finalAvg/8+" 相差 "+Math.abs(total-finalAvg/8));
                dietaryRecommendDaily.setCate1("干豆类及制品");
            }else if ("蔬菜及制品".equals(info.getCate1())){
                List<Triplet<String, String, Double>> collect = triplets.stream().filter(item -> "蔬菜及制品".equals(item.getValue0())).toList();
                 dietaryRecommendDaily =panduan(info, water, calorie, protein, fat, carbohydrate, vitamina, collect);
                //System.out.println("干豆类及制品 最后的结果值："+total+" 最优值是："+finalAvg/8+" 相差 "+Math.abs(total-finalAvg/8));
                dietaryRecommendDaily.setCate1("蔬菜及制品");
            }else if ("畜肉类及制品".equals(info.getCate1())){
                List<Triplet<String, String, Double>> collect = triplets.stream().filter(item -> "畜肉类及制品".equals(item.getValue0())).toList();
                 dietaryRecommendDaily =panduan(info, water, calorie, protein, fat, carbohydrate, vitamina, collect);
                //System.out.println("干豆类及制品 最后的结果值："+total+" 最优值是："+finalAvg/8+" 相差 "+Math.abs(total-finalAvg/8));
                dietaryRecommendDaily.setCate1("畜肉类及制品");

            }else if ("禽肉类及制品".equals(info.getCate1())){
                List<Triplet<String, String, Double>> collect = triplets.stream().filter(item -> "禽肉类及制品".equals(item.getValue0())).toList();
                 dietaryRecommendDaily =panduan(info, water, calorie, protein, fat, carbohydrate, vitamina, collect);
                //System.out.println("干豆类及制品 最后的结果值："+total+" 最优值是："+finalAvg/8+" 相差 "+Math.abs(total-finalAvg/8));
                dietaryRecommendDaily.setCate1("禽肉类及制品");


            }else if ("蛋类及制品".equals(info.getCate1())){
                List<Triplet<String, String, Double>> collect = triplets.stream().filter(item -> "蛋类及制品".equals(item.getValue0())).toList();
                 dietaryRecommendDaily =panduan(info, water, calorie, protein, fat, carbohydrate, vitamina, collect);
                //System.out.println("干豆类及制品 最后的结果值："+total+" 最优值是："+finalAvg/8+" 相差 "+Math.abs(total-finalAvg/8));
                dietaryRecommendDaily.setCate1("蛋类及制品");

            }else if ("鱼虾蟹贝类".equals(info.getCate1())){
                List<Triplet<String, String, Double>> collect = triplets.stream().filter(item -> "鱼虾蟹贝类".equals(item.getValue0())).toList();
                 dietaryRecommendDaily =panduan(info, water, calorie, protein, fat, carbohydrate, vitamina, collect);
                //System.out.println("干豆类及制品 最后的结果值："+total+" 最优值是："+finalAvg/8+" 相差 "+Math.abs(total-finalAvg/8));
                dietaryRecommendDaily.setCate1("鱼虾蟹贝类");
            }

            assert dietaryRecommendDaily != null;
            dietaryRecommendDaily.setCate2(info.getCate2());
            dietaryRecommendDaily.setDiff(CommonUtils.Keep2DecimalPlaces(Math.abs(dietaryRecommendDaily.getTotal()-finalAvg/6)));
            dietaryRecommendDaily.setCreateTime(DateTimeUtils.getNow());
            dietaryRecommendDaily.setUpdateTime(DateTimeUtils.getNow());
            dietaryRecommendDailyList.add(dietaryRecommendDaily);

        }

        //cate1 最小值
        return dietaryRecommendDailyList.stream().collect(Collectors.groupingBy(
                DietaryRecommendDaily::getCate1, Collectors.minBy(Comparator.comparingDouble(DietaryRecommendDaily::getDiff))
        ));


    }

    private static DietaryRecommendDaily panduan(NutrientsInfo info, double water, double calorie, double protein, double fat, double carbohydrate, double vitamina, List<Triplet<String, String, Double>> collect) {


        DietaryRecommendDaily dietaryRecommendDaily = new DietaryRecommendDaily();

        for (Triplet<String, String, Double> item : collect) {


            if ("water".equals(item.getValue1())) {
                double waterVolume=item.getValue2();

                water = waterVolume * info.getWaterRate();

                dietaryRecommendDaily.setWaterRateVolume(waterVolume);
                dietaryRecommendDaily.setWaterRate(water);

                /*info.setWaterRate(water);*/

                //volumeArrayList.add(nutritionWithVolume);

            } else if ("calorie".equals(item.getValue1())) {
                double calorieVolume=item.getValue2();
                calorie = calorieVolume * info.getCalorie();
                /*info.setCalorie(calorie);*/
                dietaryRecommendDaily.setCalorieVolume(calorieVolume);
                dietaryRecommendDaily.setCalorie(CommonUtils.Keep2DecimalPlaces(calorie));




            } else if ("protein".equals(item.getValue1())) {
                double proteinVolume=item.getValue2();
                protein = proteinVolume * info.getProtein();
                // info.setProtein(protein);
                // nutritionWithVolume.setProteinVolume(proteinVolume);

                dietaryRecommendDaily.setProtein(CommonUtils.Keep2DecimalPlaces(protein));
                dietaryRecommendDaily.setProteinVolume(proteinVolume);


            } else if ("fat".equals(item.getValue1())) {
                double fatVolume=item.getValue2();

                fat = fatVolume * info.getFat();
                dietaryRecommendDaily.setFat(CommonUtils.Keep2DecimalPlaces(fat));
                dietaryRecommendDaily.setFatVolume(fatVolume);

            } else if ("carbohydrate".equals(item.getValue1())) {
                double carbohydrateVolume=item.getValue2();
                carbohydrate = carbohydrateVolume * info.getCarbohydrate();
                dietaryRecommendDaily.setCarbohydrate(CommonUtils.Keep2DecimalPlaces(carbohydrate));
                dietaryRecommendDaily.setCarbohydrateVolume(carbohydrateVolume);


            } else if ("vitamina".equals(item.getValue1())) {
                double vitaminAVolume=item.getValue2();
                vitamina = vitaminAVolume * info.getVitaminA();
                dietaryRecommendDaily.setVitaminA(CommonUtils.Keep2DecimalPlaces(vitamina));
                dietaryRecommendDaily.setVitaminAVolume(vitaminAVolume);
            }

        }
        dietaryRecommendDaily.setTotal(CommonUtils.Keep2DecimalPlaces(water+calorie+protein+fat+carbohydrate+vitamina));
        return dietaryRecommendDaily;
    }


    private static Triplet<String,String,Double> calculateModulus(String nutrientsType, List<NutrientsInfo> nutrientsInfo, double avgValue, String cate1){
        //System.out.println("\n "+nutrientsType+" 的均值是:"+avgValue);
        //logger.info("{} 的均值是： {}",nutrientsType,avgValue);


        Random random = new Random();

        double maxMod=0;
        double minMod=0;
        if ("water".equals(nutrientsType)){
            List<NutrientsInfo> filteredNutrientsInfo = nutrientsInfo.stream().filter(item -> Objects.equals(item.getCate1(), cate1) && item.getWaterRate() != 0).toList();

            //系数最大值
            NutrientsInfo minValue = filteredNutrientsInfo.stream().min(Comparator.comparingDouble(NutrientsInfo::getWaterRate)).get();
             maxMod =CommonUtils.Keep2DecimalPlaces(avgValue/minValue.getWaterRate());
            //System.out.println("maxMod:"+maxMod);
            //logger.info("系数最大值: {}",maxMod);
            //系数最小值
            NutrientsInfo maxValue = filteredNutrientsInfo.stream().max(Comparator.comparingDouble(NutrientsInfo::getWaterRate)).get();
            minMod=  CommonUtils.Keep2DecimalPlaces(avgValue/maxValue.getWaterRate());
        } else if ("calorie".equals(nutrientsType)) {
            List<NutrientsInfo> filteredNutrientsInfo = nutrientsInfo.stream().filter(item -> Objects.equals(item.getCate1(), cate1) && item.getCalorie() != 0).toList();

            NutrientsInfo minValue = filteredNutrientsInfo.stream().min(Comparator.comparingDouble(NutrientsInfo::getCalorie)).get();
            maxMod =CommonUtils.Keep2DecimalPlaces(avgValue/minValue.getCalorie());
            //System.out.println("maxMod:"+maxMod);
            //logger.info("系数最大值: {}",maxMod);
            //系数最小值
            NutrientsInfo maxValue = filteredNutrientsInfo.stream().max(Comparator.comparingDouble(NutrientsInfo::getCalorie)).get();
            minMod=  CommonUtils.Keep2DecimalPlaces(avgValue/maxValue.getCalorie());

        }else if ("fat".equals(nutrientsType)) {
            List<NutrientsInfo> filteredNutrientsInfo = nutrientsInfo.stream().filter(item -> Objects.equals(item.getCate1(), cate1) && item.getFat() != 0).toList();

            NutrientsInfo minValue = filteredNutrientsInfo.stream().min(Comparator.comparingDouble(NutrientsInfo::getFat)).get();
            maxMod =CommonUtils.Keep2DecimalPlaces(avgValue/minValue.getFat());
            //System.out.println("maxMod:"+maxMod);
            //logger.info("系数最大值: {}",maxMod);
            //系数最小值
            NutrientsInfo maxValue = filteredNutrientsInfo.stream().max(Comparator.comparingDouble(NutrientsInfo::getFat)).get();
            minMod=  CommonUtils.Keep2DecimalPlaces(avgValue/maxValue.getFat());

        }else if ("protein".equals(nutrientsType)) {

            List<NutrientsInfo> filteredNutrientsInfo = nutrientsInfo.stream().filter(item -> Objects.equals(item.getCate1(), cate1) && item.getProtein() != 0).toList();

            NutrientsInfo minValue = filteredNutrientsInfo.stream().min(Comparator.comparingDouble(NutrientsInfo::getProtein)).get();
            maxMod =CommonUtils.Keep2DecimalPlaces(avgValue/minValue.getProtein());
            //System.out.println("maxMod:"+maxMod);
            //logger.info("系数最大值: {}",maxMod);
            //系数最小值
            NutrientsInfo maxValue = filteredNutrientsInfo.stream().max(Comparator.comparingDouble(NutrientsInfo::getProtein)).get();
            minMod=  CommonUtils.Keep2DecimalPlaces(avgValue/maxValue.getProtein());

        }else if ("carbohydrate".equals(nutrientsType)) {
            List<NutrientsInfo> filteredNutrientsInfo = nutrientsInfo.stream().filter(item -> Objects.equals(item.getCate1(), cate1) && item.getCarbohydrate() != 0).toList();

            NutrientsInfo minValue = filteredNutrientsInfo.stream().min(Comparator.comparingDouble(NutrientsInfo::getCarbohydrate)).get();
            maxMod =CommonUtils.Keep2DecimalPlaces(avgValue/minValue.getCarbohydrate());
            //System.out.println("maxMod:"+maxMod);
            //logger.info("系数最大值: {}",maxMod);
            //系数最小值
            NutrientsInfo maxValue = filteredNutrientsInfo.stream().max(Comparator.comparingDouble(NutrientsInfo::getCarbohydrate)).get();
            minMod=  CommonUtils.Keep2DecimalPlaces(avgValue/maxValue.getCarbohydrate());

        }else if ("vitamina".equals(nutrientsType)) {
            List<NutrientsInfo> filteredNutrientsInfo = nutrientsInfo.stream().filter(item -> Objects.equals(item.getCate1(), cate1)).toList();

            NutrientsInfo minValue = filteredNutrientsInfo.stream().min(Comparator.comparingDouble(NutrientsInfo::getVitaminA)).get();
            if (minValue.getVitaminA()==0){
                maxMod=0;
            }else {
                maxMod =CommonUtils.Keep2DecimalPlaces(avgValue/minValue.getVitaminA());
            }

            //System.out.println("maxMod:"+maxMod);
            //logger.info("系数最大值: {}",maxMod);
            //系数最小值
            NutrientsInfo maxValue = filteredNutrientsInfo.stream().max(Comparator.comparingDouble(NutrientsInfo::getVitaminA)).get();
            if (maxValue.getVitaminA()==0){
                minMod=0;
            }else {
                minMod =CommonUtils.Keep2DecimalPlaces(avgValue/maxValue.getVitaminA());
            }

        }


        //System.out.println("minMod:"+minMod);
        //logger.info("系数最小值: {}",minMod);
        double modulus;
        if (maxMod-minMod==0){
            modulus=1;
        }else {
            modulus= minMod+random.nextDouble(Math.abs(maxMod-minMod));
        }
        modulus=CommonUtils.Keep2DecimalPlaces(modulus);

        // cate1 的 每一个元素 的 系数 (也就是 量)
        return new Triplet<>(cate1,nutrientsType,modulus);







    }

    public static JSONArray formatNodes (Map<String, DietaryRecommendDaily> dietaryRecommendDailyMap,String name){

        /*JSONObject jsonObject = new JSONObject();*/
        JSONArray jsonArray = new JSONArray();


        JSONObject nameJSon = new JSONObject();
        nameJSon.put("name",name);


        jsonArray.add(nameJSon);
        Set<String> keySet = dietaryRecommendDailyMap.keySet();



        String jsonStr="{\"NutrientsInfo\":\"value\"}";
        for (String key : keySet) {
            DietaryRecommendDaily dietaryRecommendDaily = dietaryRecommendDailyMap.get(key);
            if ("蛋类及制品".equals(dietaryRecommendDaily.getCate1())){
                JSONObject item = new JSONObject();
                item.put("name",dietaryRecommendDaily.getCate2());
                jsonArray.add(item);
            }else if ("鱼虾蟹贝类".equals(dietaryRecommendDaily.getCate1())){
                JSONObject item = new JSONObject();
                item.put("name",dietaryRecommendDaily.getCate2());
                jsonArray.add(item);

            }else if ("禽肉类及制品".equals(dietaryRecommendDaily.getCate1())){
                JSONObject item = new JSONObject();
                item.put("name",dietaryRecommendDaily.getCate2());
                jsonArray.add(item);

            }else if ("畜肉类及制品".equals(dietaryRecommendDaily.getCate1())){
                JSONObject item = new JSONObject();
                item.put("name",dietaryRecommendDaily.getCate2());
                jsonArray.add(item);

            }else if ("蔬菜及制品".equals(dietaryRecommendDaily.getCate1())){
                JSONObject item = new JSONObject();
                item.put("name",dietaryRecommendDaily.getCate2());
                jsonArray.add(item);

            }else if ("干豆类及制品".equals(dietaryRecommendDaily.getCate1())){
                JSONObject item = new JSONObject();
                item.put("name",dietaryRecommendDaily.getCate2());
                jsonArray.add(item);

            }else if ("薯类、淀粉及制品".equals(dietaryRecommendDaily.getCate1())){
                JSONObject item = new JSONObject();
                item.put("name",dietaryRecommendDaily.getCate2());
                jsonArray.add(item);

            }else if ("谷物及制品".equals(dietaryRecommendDaily.getCate1())){
                JSONObject item = new JSONObject();
                item.put("name",dietaryRecommendDaily.getCate2());
                jsonArray.add(item);
            }
            String water=jsonStr.replace("NutrientsInfo","name")
                    .replace("value", dietaryRecommendDaily.getWaterRateVolume() * 100 +"g");
            jsonArray.add(JSON.parse(water));

            String calorieVolume=jsonStr.replace("NutrientsInfo","name")
                    .replace("value", dietaryRecommendDaily.getCalorieVolume() * 100 +"g");
            jsonArray.add(JSON.parse(calorieVolume));

            String proteinVolume=jsonStr.replace("NutrientsInfo","name")
                    .replace("value", dietaryRecommendDaily.getProteinVolume() * 100 +"g");
            jsonArray.add(JSON.parse(proteinVolume));

            String fatVolume=jsonStr.replace("NutrientsInfo","name")
                    .replace("value", dietaryRecommendDaily.getFatVolume() * 100 +"g");
            jsonArray.add(JSON.parse(fatVolume));

            String carbohydrateVolume=jsonStr.replace("NutrientsInfo","name")
                    .replace("value", dietaryRecommendDaily.getCarbohydrateVolume() * 100 + "g");
            jsonArray.add(JSON.parse(carbohydrateVolume));

            String vitaminAVolume=jsonStr.replace("NutrientsInfo","name")
                    .replace("value", dietaryRecommendDaily.getVitaminAVolume() * 100 +"μg");
            jsonArray.add(JSON.parse(vitaminAVolume));

        }
        return jsonArray;
    }

    public static JSONArray formatEdge(Map<String, DietaryRecommendDaily> dietaryRecommendDailyMap){
        /*JSONObject nameJson = new JSONObject();*/
        JSONArray edgeArray = new JSONArray();


        //第一层  第二层

        int i=0;

        Set<String> keySet = dietaryRecommendDailyMap.keySet();
      for (String key : keySet) {
          int n = 1 + 7 * i;
          JSONObject jsonObject = new JSONObject();
          jsonObject.put("source", 0);
          jsonObject.put("target", n);
          jsonObject.put("relation", key);
          jsonObject.put("value", 1.7);
          edgeArray.add(jsonObject);
          getEdge(n, i, dietaryRecommendDailyMap, key, edgeArray);
          i++;
      }
        return edgeArray;
    }

    public static void saveDietaryGraph(DBTemplate<DietaryRecommendDaily> dbTemplate, Map<String, DietaryRecommendDaily> map,String userName) throws Exception {
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            DietaryRecommendDaily dietaryRecommendDaily = map.get(key);
            dietaryRecommendDaily.setUserName(userName);
            dbTemplate.save("dietary_recommend_daily", DietaryRecommendDaily.class,dietaryRecommendDaily,true);
        }
    }


    public static void getEdge(int n ,int i,Map<String, DietaryRecommendDaily> dietaryRecommendDailyMap,String key,JSONArray edgeArray){
        String jsonStr="{\"source\":${source},\"value\":${value},\"target\":${target},\"relation\":\"${relation}\"}";
        for (int j=n+1; j<1+7*(i+1);j++){
            String first= jsonStr.replace("${source}",String.valueOf(n))
                    .replace("${target}",String.valueOf(j));
            if (j==n+1){
                first=first.replace("${relation}","waterVolume")
                        .replace("${value}",String.valueOf(2));
            }else if (j==n+2){
                first=first.replace("${relation}","calorieVolume")
                        .replace("${value}",String.valueOf(2));
            }else if (j==n+3){
                first=first.replace("${relation}","proteinVolume")
                        .replace("${value}",String.valueOf(2));
            }else if (j==n+4){
                first=first.replace("${relation}","fatVolume")
                        .replace("${value}",String.valueOf(2));
            }else if (j==n+5){
                first=first.replace("${relation}","carbohydrateVolume")
                        .replace("${value}",String.valueOf(2));
            }else if (j==n+6){
                first=first.replace("${relation}","vitaminAVolume")
                        .replace("${value}",String.valueOf(2));
            }
            //System.out.println(first);
            edgeArray.add(JSON.parse(first));
        }
    }

}
